home *** CD-ROM | disk | FTP | other *** search
- #include "fractal.h"
-
- #include<exec/tasks.h>
-
- #include<stdlib.h>
- #include<stdio.h>
-
- #include "gadgets.h"
-
- #include<clib/alib_protos.h>
- #include<clib/exec_protos.h>
- #include<clib/graphics_protos.h>
-
- static int calc(double, double, int);
- static void fractal(void);
-
- /* The mechanism by which we will control our task: */
- /* One Semaphore for drawing, the other for running */
- static struct SignalSemaphore drawing;
- static struct SignalSemaphore running;
-
- /* Initialisation done when program is started */
- void initSemaphores()
- {
- InitSemaphore(&drawing);
- InitSemaphore(&running);
- }
-
- /* To stop the fractal we stop it drawing then stop our */
- /* task from running */
- void stopFractal()
- {
- ObtainSemaphore(&drawing);
- ObtainSemaphore(&running);
- ReleaseSemaphore(&running);
- ReleaseSemaphore(&drawing);
- }
-
- /* A local copy of the window pointer for our task */
- static struct Window* win;
-
- /* Draw a fractal in the window */
- void drawFractal(struct Window* w)
- {
- /* If the semaphore is available a task is not already running */
- if(AttemptSemaphore(&running))
- {
- struct Task* task;
- ReleaseSemaphore(&running);
- /* Make a copy of the window pointer for the task to use */
- win = w;
- /* Create a new task which will draw the fractal */
- task = CreateTask("HelloPainter-Fractal",-1,&fractal,4096);
- if(task == NULL)
- printf("Error: could not create task\n");
- }
- else
- /* The semaphore was already taken, so stop the task */
- stopFractal();
- }
-
- /* The starting point of our task */
- static void __saveds fractal()
- {
- /* If the semaphore is available we can start running */
- if(AttemptSemaphore(&running))
- {
- /* The width, height and number of colours for drawing */
- int w=win->Width, h=win->Height, d=1<<win->WScreen->BitMap.Depth;
- /* The snapshot of the mandelbrot set to draw */
- /* (Adjust these numbers to draw different fractals) */
- double width=4.0, height=4.0, top=-2.0, left=-2.5;
- double* array = malloc(h*sizeof(double));
- if(array)
- {
- int x;
- /* Load the array with the vertical values */
- for(x=0; x<h; x++)
- array[x]=x*height/h+top;
- /* Check whether we can continue drawing on each x */
- for(x=0; x<w && AttemptSemaphore(&drawing); x++)
- {
- /* Precalculate the horizontal value */
- double xr = x*width/w+left;
- int y;
- for(y=0; y<h; y++)
- {
- /* Set the current colour, using our precalculated values */
- setFgPen(win, calc(xr,array[y],d));
- /* Draw the pixel */
- WritePixel(win->RPort,x,y);
- }
- /* Release the semaphore before checking again */
- ReleaseSemaphore(&drawing);
- }
- /* Now we've finished, release the memory from the malloc()ed array */
- free(array);
- }
- /* Release the semaphore to indicate the task has finished */
- ReleaseSemaphore(&running);
- }
- }
-
- /* Calculate the colour of a particular point */
- /* (This is the number of iterations of the equation */
- /* needed to exceed the bound value) */
- static int calc(double x, double y, int d)
- {
- double xc=x, yc=y;
- double xsq=x*x, ysq=y*y;
- int it;
- /* Adjust the 16.0 to give different colour spreads */
- for(it=0; it<d && xsq+ysq<16.0; it++)
- {
- yc = 2.0*xc*yc+y;
- xc = xsq-ysq+x;
- xsq = xc*xc;
- ysq = yc*yc;
- }
- return it;
- }
-